package parser

import (
	"fmt"
	"monkey/ast"
	"monkey/lexer"
	"monkey/token"
	"strconv"
)

//定义Monkey语言的优先级
const (
	_ int = iota
	LOWEST
	EQUALS//==
	LESSGREATER//> or <
	SUM//+
	PRODUCT //*
	PREFIX  //-X or !X
	CALL 	//myFunction(X)
	INDEX //array[index]//INDEX在所有定义的优先级常量中拥有最高的优先级
)
type Parser struct{
	l *lexer.Lexer//l是指向词法分析器实例的指针
	errors []string//错误处理

	curToken token.Token//指向输入中的当前词法单元
	peekToken token.Token//指向下一个词法单元
	
	prefixParseFns map[token.TokenType]prefixParseFn
	infixParseFns   map[token.TokenType]infixParseFn
}	

type (
	prefixParseFn func() ast.Expression//前缀解析函数
	infixParseFn func(ast.Expression) ast.Expression//中缀解析函数
	/*infixParseFn接受另一个ast.Expression作为参数。
	该参数是所解析的中缀运算符左侧的内容。
	根据定义，前缀运算符左侧为空*/
)

func New(l *lexer.Lexer) *Parser{
	p := &Parser{
		l:l,
		errors: []string{},
	}
	p.prefixParseFns = make(map[token.TokenType]prefixParseFn)
	p.registerPrefix(token.IDENT,p.parseIdentifier)
	p.registerPrefix(token.INT,p.parseIntegerLiteral)
	p.registerPrefix(token.BANG, p.parsePrefixExpression)
	p.registerPrefix(token.MINUS, p.parsePrefixExpression)
	p.registerPrefix(token.TRUE,p.parseBoolean)
	p.registerPrefix(token.FALSE,p.parseBoolean)
	p.registerPrefix(token.LPAREN,p.parseGroupedExpression)
	p.registerPrefix(token.IF,p.parseIfExpression)
	p.registerPrefix(token.FUNCTION,p.parseFunctionLiteral)
	p.registerPrefix(token.STRING,p.parseStringLiteral)
	p.registerPrefix(token.LBRACKET,p.parseArrayLiteral)
	p.registerPrefix(token.LBRACE,p.parseHashLiteral)
	p.registerPrefix(token.MACRO,p.parseMacroLiteral)
	p.infixParseFns = make(map[token.TokenType]infixParseFn)
	p.registerInfix(token.PLUS, p.parseInfixExpression)
    p.registerInfix(token.MINUS, p.parseInfixExpression)
    p.registerInfix(token.SLASH, p.parseInfixExpression)
    p.registerInfix(token.ASTERISK, p.parseInfixExpression)
    p.registerInfix(token.EQ, p.parseInfixExpression)
    p.registerInfix(token.NOT_EQ, p.parseInfixExpression)
    p.registerInfix(token.LT, p.parseInfixExpression)
    p.registerInfix(token.GT, p.parseInfixExpression)
	p.registerInfix(token.LPAREN,p.parseCallExpression)
	p.registerInfix(token.LBRACKET,p.parseIndexExpression)
	//读取两个词法单位，以设置curToken和peekToken
	p.nextToken()
	p.nextToken()
	return p
}

func (p *Parser)nextToken(){
	p.curToken = p.peekToken
	p.peekToken = p.l.NextToken()
}//可以同时后移curToken和peekToken

/*ParseProgram要做的第一件事是构造AST的根节点，也就是*ast.Program。
然后遍历输入中的每个词法单元，直到遇见token.EOF词法单元。这通过重复调用nextToken完成，
nextToken会同时前移p.curToken和p.peekToken。每次迭代都会调用parseStatement，
它每次解析一条语句。如果parseStatement返回的不是nil，而是一个ast.Statement，
那么这个返回值会被添加到AST根节点的Statements切片中。所有内容都解析完成后，就返回*ast.Program根节点。*/
func (p *Parser)ParseProgram() *ast.Program{
	program := &ast.Program{}
	program.Statements = []ast.Statement{}
	for !p.curTokenIs(token.EOF){
		stmt := p.parseStatement()
		if stmt != nil{
			program.Statements = append(program.Statements, stmt)
		}
		p.nextToken()
	}
	return program
}

func (p *Parser)parseStatement() ast.Statement{
	
	switch p.curToken.Type{
	case token.LET:
		return p.parseLetStatement()
	case token.RETURN:
		return p.parseReturnStatement()
	default:
		return p.parseExpressionStatement()
	}
}

func (p *Parser) parseLetStatement() *ast.LetStatement{
	stmt := &ast.LetStatement{Token:p.curToken}

	if !p.expectPeek(token.IDENT){
		return nil
	}
	stmt.Name = &ast.Identifier{Token:p.curToken,Value:p.curToken.Literal}

	if !p.expectPeek(token.ASSIGN){
		return nil
	}
	p.nextToken()//吃掉"="
	stmt.Value = p.parseExpression(LOWEST)
	if p.peekTokenIs(token.SEMICOLON){
		p.nextToken()
	}
	return stmt
}

func (p *Parser) parseReturnStatement() *ast.ReturnStatement{
	stmt := &ast.ReturnStatement{Token:p.curToken}
	p.nextToken()
	stmt.ReturnValue = p.parseExpression(LOWEST)
	if p.peekTokenIs(token.SEMICOLON){
		p.nextToken()
	}
	return stmt
}
//expectPeek 判断下一个词法单元是不是我们想要的类型，是的话后移一个词法单位
/*几乎所有语法分析器都有断言函数，expectPeek方法就是其中之一。
断言函数的主要目的是通过检查下一个词法单元的类型，确保词法单元顺序的正确性*/
func (p *Parser)expectPeek(tk token.TokenType)bool{
	if p.peekTokenIs(tk){
		p.nextToken()
		return true
	}else{
		p.peekError(tk)//每次对下一个词法单元的期望出错时可以自动添加错误
		return false
	}
}

//curTokenIs 判断指向当前词法单元的类型是不是想要的类型
func (p *Parser) curTokenIs(t token.TokenType)bool{
	return p.curToken.Type ==  t
}

//peekTokenIs 判断指向下一个词法单元的类型是不是想要的类型
func (p *Parser) peekTokenIs(t token.TokenType)bool{
	return p.peekToken.Type == t
}
//Errors 返回Parse的错误
func (p *Parser) Errors() []string{
	return p.errors
}

//peekError
func (p *Parser) peekError(t token.TokenType) {
	msg := fmt.Sprintf("expected next token to be %s,got %s instead",
	t,
	p.peekToken.Type)
	p.errors = append(p.errors, msg)
}

func (p *Parser) registerPrefix(tokenType token.TokenType,fn prefixParseFn){
	p.prefixParseFns[tokenType] = fn
}

func (p *Parser) registerInfix(tokenType token.TokenType,fn infixParseFn){
	p.infixParseFns[tokenType] = fn
}

func (p *Parser) parseExpressionStatement() *ast.ExpressionStatement{
	defer untrace(trace("parseExpressionStatement"))
	stmt := &ast.ExpressionStatement{Token:p.curToken}
	stmt.Expression = p.parseExpression(LOWEST)

	if p.peekTokenIs(token.SEMICOLON){//检查(可选)的分号
		p.nextToken()
	}
	return stmt
}

func (p *Parser) parseExpression(precedence int) ast.Expression{
	defer untrace(trace("parseExpression"))
	prefix := p.prefixParseFns[p.curToken.Type]
	if prefix == nil{
		p.noPrefixParseFnError(p.curToken.Type)
		return nil
	}
	leftExp := prefix()

	for !p.peekTokenIs(token.SEMICOLON) && precedence < p.peekPrecedence(){
		infix := p.infixParseFns[p.peekToken.Type]
		if infix == nil{
			return leftExp
		}
		p.nextToken()
		leftExp = infix(leftExp)
	}
	/*这里的新内容是位于parseExpression中的循环。在循环的主体中，
	该方法尝试为下一个词法单元查找infixParseFns。如果找到了这个函数，
	就用prefixParseFn返回的表达式作为参数来调用这个函数。
	这个循环会重复执行，直到遇见优先级更低的词法单元*/
	return leftExp
}
//parseIdentifier 将当前词法单元及其字面量分别提供给*ast.Identifier的Token和Value字段
func (p *Parser) parseIdentifier() ast.Expression{
	return &ast.Identifier{Token:p.curToken,Value:p.curToken.Literal}
}

func (p *Parser) parseIntegerLiteral() ast.Expression{
	defer untrace(trace("parseIntegerLiteral"))
	lit := &ast.IntegerLiteral{Token:p.curToken}
	value,err := strconv.ParseInt(p.curToken.Literal,0,64)
	if err != nil{
		msg := fmt.Sprintf("could not parse %q as integer",p.curToken.Literal)
		p.errors = append(p.errors,msg)
		return nil
	}
	lit.Value = value
	return lit
}

//noPrefixParseFnError只是将格式化的错误消息添加到语法分析器的errors字段中
//相应的TokenType没有找到相应的前缀解析函数注册
func (p *Parser) noPrefixParseFnError(t token.TokenType){
	msg := fmt.Sprintf("no prefix parse function for %s found",t)
	p.errors = append(p.errors, msg)
}

func (p *Parser) parsePrefixExpression() ast.Expression{
	defer untrace(trace("parsePrefixExpression"))
	expression := &ast.PrefixExpression{
		Token:p.curToken,
		Operator: p.curToken.Literal,
	} 
	p.nextToken()
	expression.Right = p.parseExpression(PREFIX)
	/*当parsePrefixExpression调用parseExpression时，
	词法单元已经前移了，此时词法单元是前缀运算符后面的内容。
	对于-5来说，调用parseExpression时，p.curToken.Type为token.INT。
	然后parseExpression检查已注册的前缀解析函数，
	会找到parseIntegerLiteral，后者将构建一个*ast.IntegerLiteral节点并将其返回。
	在parseExpression构造并返回这个节点后，parsePrefixExpression会使用
	该节点填充*ast.PrefixExpression的Right字段。*/
	return expression
}

//优先级表
var precedences = map[token.TokenType]int{
	token.EQ:EQUALS,
	token.NOT_EQ:EQUALS,
	token.LT:LESSGREATER,
	token.GT:LESSGREATER,
	token.PLUS:SUM,
	token.MINUS:SUM,
	token.SLASH:PRODUCT,
	token.ASTERISK:PRODUCT,
	token.LPAREN:CALL,
	token.LBRACKET:INDEX,
}

//peekPrecedence 看下一个词法单位的优先级
func (p *Parser) peekPrecedence() int{
	if p,ok := precedences[p.peekToken.Type];ok{
		return p
	}
	return LOWEST
}
//curPrecedence 看当前词法单位的优先级
func (p *Parser) curPrecedence() int{
	if p,ok := precedences[p.curToken.Type];ok{
		return p
	}
	return LOWEST
}

func (p *Parser) parseInfixExpression(left ast.Expression) ast.Expression{
	defer untrace(trace("parseInfixExpression"))
	expression := &ast.InfixExpression{
		Token: p.curToken,
		Operator: p.curToken.Literal,
		Left: left,
	}
	/*这个新方法有一个名为left的参数，其类型为ast.Expression。
	该方法使用这个参数构造一个*ast.InfixExpression节点，
	其中参数left会填充到Left字段中。然后先将当前词法单元的
	优先级（中缀表达式的运算符）分配给局部变量precedence，
	之后再调用nextToken前移词法单元，最后再次调用parseExpression
	来填充节点的Right字段，这次传入的是运算符词法单元的优先级。*/
	precedence := p.curPrecedence()
	p.nextToken()
	expression.Right = p.parseExpression(precedence)
	// if expression.Operator == "+"{
	// 	expression.Right = p.parseExpression(precedence-1)
	// }else{
	// 	expression.Right = p.parseExpression(precedence)
	// }
	
	return expression
}

func (p *Parser) parseBoolean() ast.Expression{
	return &ast.Boolean{Token:p.curToken,Value:p.curTokenIs(token.TRUE)}
}

func (p *Parser) parseGroupedExpression() ast.Expression{
	p.nextToken()
	exp := p.parseExpression(LOWEST)

	if !p.expectPeek(token.RPAREN){
		return nil
	}
	return exp
}
//parseIfExpression  if (<条件>) <结果> else <可替代的结果>
func (p *Parser) parseIfExpression() ast.Expression	{
	expression := &ast.IfExpression{Token:p.curToken}
	if !p.expectPeek(token.LPAREN){
		return nil
	}
	p.nextToken()
	expression.Condition = p.parseExpression(LOWEST)
	if !p.expectPeek(token.RPAREN){
		return nil
	}
	if !p.expectPeek(token.LBRACE){
		return nil
	}
	expression.Consequence = p.parseBlockStatement()
	if p.peekTokenIs(token.ELSE){
		p.nextToken()
		if !p.expectPeek(token.LBRACE){
			return nil
		}
		expression.Alternative = p.parseBlockStatement()
	}
	return expression
}

func (p *Parser) parseBlockStatement()*ast.BlockStatement{
	block := &ast.BlockStatement{Token:p.curToken}
	block.Statements = []ast.Statement{}
	p.nextToken()
	/*arseBlockStatement不断调用parseStatement，直到遇见右大括号}
	或token.EOF，前者表示到了块语句的末尾，后者表示没有要解析的词法单元了*/
	for !p.curTokenIs(token.RBRACE) && !p.curTokenIs(token.EOF){
		stmt := p.parseStatement()
		if stmt != nil{
			block.Statements =append(block.Statements, stmt)
		}
		p.nextToken()
	}
	return block
}

func (p *Parser) parseFunctionLiteral() ast.Expression{
	lit := &ast.FunctionLiteral{Token:p.curToken}
	if !p.expectPeek(token.LPAREN){
		return nil
	}
	lit.Parameters = p.parseFunctionParameters()

	if !p.expectPeek(token.LBRACE){
		return nil
	}
	lit.Body = p.parseBlockStatement()
	return lit
}

func (p *Parser) parseFunctionParameters() []*ast.Identifier{
	Identifiers := []*ast.Identifier{}
	if p.peekTokenIs(token.RPAREN){
		p.nextToken()
		return Identifiers
	}
	//println(p.curToken.Literal)
	p.nextToken()
	ident := &ast.Identifier{Token:p.curToken,Value:p.curToken.Literal}
	Identifiers = append(Identifiers, ident)
	for p.peekTokenIs(token.COMMA){
		p.nextToken()
		p.nextToken()
		ident := &ast.Identifier{Token:p.curToken,Value:p.curToken.Literal}
		Identifiers = append(Identifiers, ident)
	}
	if !p.expectPeek(token.RPAREN){
		return nil
	}
	//p.nextToken()//吃掉参数列表的最后一个)，再返回
	return Identifiers
}

func (p *Parser) parseCallExpression(function ast.Expression)ast.Expression{
	exp := &ast.CallExpression{Token:p.curToken,Function:function}
	exp.Arguments = p.parseExpressionList(token.RPAREN)
	return exp
}

func (p *Parser) parseCallArguments()[]ast.Expression{
	args := []ast.Expression{}
	if p.peekTokenIs(token.RPAREN){
		p.nextToken()
		return args
	}
	p.nextToken()//吃掉左括号
	args = append(args, p.parseExpression(LOWEST))
	for p.peekTokenIs(token.COMMA){
		p.nextToken()
		p.nextToken()
		args = append(args, p.parseExpression(LOWEST))
	}
	if !p.expectPeek(token.RPAREN){
		return nil
	}

	return args
}

func (p *Parser) parseStringLiteral() ast.Expression{
	return &ast.StringLiteral{Token:p.curToken,Value: p.curToken.Literal}
}

func (p *Parser) parseArrayLiteral() ast.Expression{
	array := &ast.ArrayLiteral{Token:p.curToken}
	array.Elements = p.parseExpressionList(token.RBRACKET)
	return array
}

func (p *Parser) parseExpressionList(end token.TokenType) []ast.Expression{
	list := []ast.Expression{}

	if p.peekTokenIs(end){
		p.nextToken()
		return list
	}

	p.nextToken()
	list = append(list, p.parseExpression(LOWEST))

	for p.peekTokenIs(token.COMMA){
		p.nextToken()
		p.nextToken()
		list = append(list, p.parseExpression(LOWEST))
	}

	if !p.expectPeek(end){
		return nil
	}
	return list
}

//parseIndexExpression 也就是将myArray[0]中的[视为中缀运算符，将myArray视为左操作数，将0视为右操作数。
func (p *Parser) parseIndexExpression(left ast.Expression) ast.Expression{
	exp := &ast.IndexExpression{Token:p.curToken,Left:left}
	p.nextToken()
	exp.Index = p.parseExpression(LOWEST)
	if !p.expectPeek(token.RBRACKET){
		return nil
	}
	return exp
}

func (p *Parser) parseHashLiteral() ast.Expression{
	hash := &ast.HashLiteral{Token:p.curToken}
	hash.Pairs = make(map[ast.Expression]ast.Expression)

	for !p.peekTokenIs(token.RBRACE){
		p.nextToken()
		key := p.parseExpression(LOWEST)
		if !p.expectPeek(token.COLON){
			return nil
		}
		p.nextToken()
		val := p.parseExpression(LOWEST)
		hash.Pairs[key] = val
		if !p.peekTokenIs(token.RBRACE){
			if !p.expectPeek(token.COMMA){
				return nil
			}
		}
	}
	if !p.expectPeek(token.RBRACE){
		return nil
	}
	return hash
}

func (p *Parser) parseMacroLiteral() ast.Expression{
	lit := &ast.MacroLiteral{}

	if !p.expectPeek(token.LPAREN){
		return nil
	}
	lit.Parameters = p.parseFunctionParameters()//复用函数参数处理的函数

	if !p.expectPeek(token.LBRACE){
		return nil
	}
	lit.Body = p.parseBlockStatement()
	return lit
}